package com.edu.springmvc.helloworld.controller;

import com.edu.springmvc.helloworld.bean.Employee;
import com.edu.springmvc.helloworld.common.R;
import com.edu.springmvc.helloworld.exception.BusinessException;
import com.edu.springmvc.helloworld.exception.BusinessExceptionEnum;
import com.edu.springmvc.helloworld.service.EmployeeService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

/**
 * CORS policy: Cross-Origin Resource Sharing (CORS)：跨域问题
 * 同源策略
 * 跨源资源共享（CORS）
 * 浏览器为了安全，默认会遵循同源策略（请求要去的服务器和当前项目所在的服务器必须是同一个源【同一个服务器】，如果不是，请求会被拦截，请求失败）。
 * <p>
 * 浏览器页面所在地址： http://localhost/employee/base
 * 页面上要发去的请求： http://localhost:8080/employee/getEmployeeById?id=1
 * /以前的东西，必须完全一样，一个字母不一样，就会失败。
 * <p>
 * 复杂的跨域请求会发送两次：
 * 1. OPTIONS请求：请求服务器，询问是否允许发送真正的请求
 * 2. 正常请求：发送真正的请求
 * <p>
 * 跨域问题：
 * 1.前端自己解决
 * 2.后端解决，允许前端跨域请求
 * 原理：服务器给浏览器响应一个响应头：Access-Control-Allow-Origin: *
 * <p>
 * 设计模式：单一职责；
 * 各种xxO：JavaBean也要分层
 * Pojo: 普通Java类
 * Dao: 数据访问层 Database Access Object
 * TO: Transfer Object: 传输对象 专门用来传输数据的对象
 * VO: View Object: 值对象，视图对象（专门用来封装前端数据的对象）
 * DTO: Data Transfer Object: 数据传输对象
 * CO: Controller Object: 控制器对象
 * BO: Business Object: 业务对象（Service），专门用来封装业务逻辑的对象
 */
@Tag(name = "员工管理") // 描述controller类的作用
@RestController
@CrossOrigin // 允许跨域请求
public class EmployeeController {
    @Autowired
    private EmployeeService employeeService;

    @Operation(summary = "查询所有员工信息")
    @GetMapping("/employees")
    public R<List<Employee>> getEmployees() {
        List<Employee> employees = employeeService.getEmployees();
        // 模拟异常
        if (employees == null)
            throw new BusinessException(BusinessExceptionEnum.USER_NOT_ADMIN);
        return R.success(employees);
    }

    /**
     * 统一处理异常
     * 如果controller本类出现异常，会自动在本类中找有没有@ExceptionHandler注解的方法，如果有，就执行这个方法。
     * 它的返回值，会作为响应返回给前端。
     *
     * @param e 异常
     * @return 错误信息
     */
    @ExceptionHandler(ArithmeticException.class)
    public R<String> handleArithmeticException(ArithmeticException e) {
        return R.error("出现异常：" + e.getMessage(), 100);
    }

    /**
     * JSR 303 是Java语言的规范，用于数据验证
     * <p>
     * 数据校验：
     * 1. 导入校验包
     * 2. 编写校验注解
     * 3. 使用 @valid 告诉 SpringMVC 进行校验
     * 效果1：如果校验不通过，目标方法不执行
     * (以后不用)4. 在 @Valid 参数后面，紧跟一个 BindingResult 对象，封装校验结果
     * 效果2： 全局异常处理机制
     * 5.编写一个全局异常处理器，处理 MethodArgumentNotValidException (校验出错的异常),  统一返回校验失败的提示信息
     */
    @PostMapping("/employee")
    public R<Map<String, String>> insertEmployee(@RequestBody @Valid Employee employee /* BindingResult bindingResult */) {
        return R.success();
    }
}
